#include <stdbool.h>
#include "stdio.h"
#include "limits.h"
int aaa= 16666;
void testVariables() {
    // 变量声明时，就为它分配内存空间，但是不会清除内存里面原来的值。这导致声明变量以后，变量会是一个随机的值。所以，变量一定要赋值以后才能使用。
    int age;
    printf("未初始化变量，系统会把未清除的值赋给该变量 ，age = %d \n", age);
    age = 18;
    printf("初始化的 age = %d\n", age);

    // 变量的作用域(scope)：
    // 1. 文件作用域（file scope） ： 在源码文件顶层声明的变量，从声明的位置到文件结束都有效；
    // 2. 块作用域（block scope） ： 是由大括号（ {} ）组成的代码块，只在当前代码块有效，代码块外部不可见。

}
// 基本类型
void testBaseTypes() {
    // C语言中，没有字符串，用字符数组表示字符串；
    // C语言中，void 表示空类型（无类型）；
    // 整形类型
    // short(2 byte),int(4 byte),long(4 byte or 8 byte),long long(8 byte)
    // 不同计算机的 int 类型的大小是不一样的。比较常见的是使用4个字节（32位）存储一个 int 类型的值

    printf("当前计算机int 类型数据 的最小值 ：%d\n", INT_MIN);
    printf("当前计算机int 类型数据 的最大值 ：%d\n", INT_MAX);

    //浮点数
    // float（4 byte）,double（8 byte）,long double（12 byte）

    //字符
    // char(1 byte)，采用ASCII 码表示

    // 布尔
    bool is_true = true;
    printf("is_true = %d\n", is_true);  // 返回 false = 0,true = 1
}

// 类型转换
void testTypeConversion(){
    // 隐式类型转换,
    float y = 12 * 2; //整数赋值给浮点数变量时，会自动转为浮点数。结果24.0

    int i1 = 10;
    double d1 = 12.3;
    double s1 = i1 + d1; //系统自动将i的类型由int转换为double类型，故i+d1结果为double类型

    double d2 = 3.14159;
    int i2 = d2; // 强制大转小，会失去精度

    // 强制转换
    int i3 = (int) d2;
}

/**
 * 测试各种常量类型的函数
 */
void testConst(){
    //常量
    // 1.字面常量
    3.14159;  // 浮点数字面常量
    'a';      // 字符字面常量
    // 2.const 常量
    const int height = 18;  // 使用const关键字定义的整型常量
    printf("const 常量 height = %d\n", height);  // 输出const常量的值

    // 3.枚举常量
    enum Color {  // 定义颜色枚举类型
        red,     // 枚举常量red，默认值为0
        blue,    // 枚举常量blue，默认值为1
        green    // 枚举常量green，默认值为2
    };
    printf("枚举常量 color = %d\n", red);  // 输出枚举常量red的值

    // 4. define 常量,宏常量
    #define PI 3.14159  // 使用define预处理指令定义的宏常量PI
    printf("define 常量(宏常量) PI = %f\n", PI);  // 输出宏常量PI的值
}
/**
 * 测试输入输出
 * 输入函数：
 *      scanf()，是格式输入函数，可接收`任意类型`的数据。
 *      getchar()，是`字符`输入函数， 只能接收`单个字符`。
 *      gets()，是`字符串`输入函数。
 * 输出函数：
 *      printf()，是格式输出函数，可输出`任意类型`的数据。
 *      putchar()，是`字符`输出函数，只能输出`单个字符`。
 *      puts()，是`字符串`输出函数。
 */
void testInputOutput() {
    // scanf() 一般用于变量赋值
//    int int1, int2;
//    printf("请输入两个整数：");
//    // 空格隔开 或者 换行隔开
//    scanf("%d %d", &int1, &int2); // &int1,&int2 表示将输入的值赋给 int1,int2
//    printf("%d + %d = %d\n", int1, int2, int1 + int2);
//
//    printf("请重新输入两个整数：");
//    // 逗号隔开
//    scanf("%d,%d", &int1, &int2);
//    printf("%d - %d = %d\n", int1, int2, int1 - int2);

//    printf("请输入一个字符：");
//    char ch;
//    scanf("%c", &ch);
//    printf("你输入的字符是：%c\n", ch);

//    printf("请输入一个字符：");
//    char ch2 = getchar();
//    printf("你输入的字符是：%c\n", ch2);

//    printf("请输入一个字符串：");
//    char str[100];
//    gets(str);
//    puts("你输入的字符串是：");
//    puts(str);
}
// 测试数据类型的大小
void testSizeof(){
    // sizeof() 获取变量类型数据大小
    printf("bool类型数据大小 : %lu,%lu\n", sizeof(true), sizeof(bool));
    printf("char类型数据大小 : %lu,%lu\n", sizeof('a'), sizeof(char));
    printf("short类型数据大小 : %lu,%lu\n", sizeof((short) 12), sizeof(short));
    printf("int类型数据的大小 : %lu,%lu\n", sizeof(12), sizeof(int));
    printf("long类型数据大小 : %lu,%lu\n", sizeof(12L), sizeof(long));
    printf("long long类型数据大小 : %lu,%lu\n", sizeof(12LL), sizeof(long long));
    printf("float类型数据大小 : %lu,%lu\n", sizeof(12.3F), sizeof(float));
    printf("double类型数据大小 : %lu,%lu\n", sizeof(12.3), sizeof(double));
    printf("long double类型数据大小 : %lu,%lu\n", sizeof(12.3L), sizeof(long double));
}
/**
 * 变量
 * 全局（global）变量 / 外部（extern）变量： 在函数外部定义的变量，全程序有效，在定义处叫做全局变量，在引用处叫做外部变量。
 * 局部（local）变量 / 动态（auto）变量 ：在函数内部定义的变量，只在当前函数有效，但会自动释放其内存。
 * 静态（status）变量 ：只能再当前文件中使用，不会销毁，而是继续保留在内存中。
 * 静态局部（status local）变量：在函数内部定义的变量，只在当前函数有效，但会保留其值，下次调用时，变量的值不会丢失。
 * 静态全局（status global）变量 ：在函数外部定义的变量，只在当前文件有效，但会保留其值，下次调用时，变量的值不会丢失。
 * 寄存器（register）变量 ：在函数内部定义的变量，只存在于当前函数的寄存器中。
 *
   栈内存布局
   +------------------+
   |     栈(stack)    |  ← 局部变量、函数参数
   +------------------+
   |                  |
   |                  |
   |                  |
   +------------------+
   |     堆(heap)     |  ← malloc/new动态分配
   +------------------+
   |    .bss段        |  ← 未初始化 静态/全局 变量
   +------------------+
   |    .data段       |  ← 已初始化 静态/全局 变量
   +------------------+
   |    代码段(text)   |  ← 程序指令
   +------------------+
 */
int globalVar = 10; // 全局变量

void testLocalAndGlobalVariable(){
    //- 局部变量：系统不会对其默认初始化，必须对局部变量初始化后才能使用，否则，程序运行后可能会异常退出。
    //- 全局变量：如果没有显式初始化，它们会被自动、默认初始化为零或空值，具体取决于数据类型。
    //- 局部变量：保存在栈中，函数被调用时才动态地为变量分配存储单元。
    //- 全局变量：保存在内存的`全局存储区`中，占用静态的存储单元。`全局变量`大多存放在静态存储区中。
}

// int main() {
// //    testVariables();
// //    testBaseTypes();
// //    testTypeConversion();
// //    testConst();
// //    testInputOutput();
// //    testSizeof();
//     testLocalAndGlobalVariable();
// }